package com.autoerp;

import java.sql.Connection;
import java.util.Locale;

import com.autoerp.action.LoginAction;
import com.autoerp.action.UserAction;
import com.autoerp.action.UsuarioAction;
import com.autoerp.action.administracao.CidadeAction;
import com.autoerp.action.carro.CarroAction;
import com.autoerp.action.cliente.ClienteAction;
import com.autoerp.action.servico.OrdemServicoAction;
import com.autoerp.dao.UserDAO;
import com.autoerp.dao.UsuarioDAO;
import com.autoerp.dao.administracao.CidadeDAO;
import com.autoerp.dao.administracao.UfDAO;
import com.autoerp.dao.carro.CarroDAO;
import com.autoerp.dao.cliente.ClienteDAO;
import com.autoerp.dao.jdbc.JdbcUserDAO;
import com.autoerp.dao.jdbc.UsuarioDAOJdbc;
import com.autoerp.dao.jdbc.administracao.CidadeDAOJdbc;
import com.autoerp.dao.jdbc.administracao.UfDAOJdbc;
import com.autoerp.dao.jdbc.carro.CarroDAOJdbc;
import com.autoerp.dao.jdbc.cliente.ClienteDAOJdbc;
import com.autoerp.dao.jdbc.servico.DemandaDAOJdbc;
import com.autoerp.dao.jdbc.servico.OrdemServicoDAOJdbc;
import com.autoerp.dao.jdbc.servico.PecaDAOJdbc;
import com.autoerp.dao.jdbc.servico.ServicoDAOJdbc;
import com.autoerp.dao.jdbc.servico.ServicoPrestadoDAOJdbc;
import com.autoerp.dao.servico.DemandaDAO;
import com.autoerp.dao.servico.OrdemServicoDAO;
import com.autoerp.dao.servico.PecaDAO;
import com.autoerp.dao.servico.ServicoDAO;
import com.autoerp.dao.servico.ServicoPrestadoDAO;
import com.autoerp.model.Group;
import com.autoerp.model.Language;
import com.autoerp.model.User;

import org.mentabean.BeanConfig;
import org.mentabean.BeanManager;
import org.mentabean.BeanSession;
import org.mentabean.DBType;
import org.mentabean.DBTypes;
import org.mentabean.util.PropertiesProxy;
import org.mentabean.util.SQLUtils;
import org.mentawai.action.LogoutAction;
import org.mentawai.ajax.AjaxConsequence;
import org.mentawai.ajax.renderer.JSONGenericRenderer;
import org.mentawai.ajax.renderer.JSONMapAjaxRenderer;
import org.mentawai.ajax.renderer.JsonRenderer;
import org.mentawai.core.ApplicationManager;
import org.mentawai.core.Context;
import org.mentawai.core.Props;
import org.mentawai.db.ConnectionHandler;
import org.mentawai.db.mysql.MySQLBoneCPConnectionHandler;
import org.mentawai.filter.AuthenticationFilter;
import org.mentawai.filter.BlacklistParamFilter;
import org.mentawai.filter.ExceptionFilter;
import org.mentawai.filter.MentaContainerFilter;
import org.mentawai.filter.TransactionFilter;
import org.mentawai.filter.ValidationFilter;
import org.mentawai.list.DBListData;
import org.mentawai.mail.Email;

import com.autoerp.model.administracao.CidadeEntity;
import com.autoerp.model.administracao.UfEntity;
import com.autoerp.model.administracao.UsuarioEntity;
import com.autoerp.model.carro.CarroEntity;
import com.autoerp.model.cliente.ClienteEntity;
import com.autoerp.model.servico.DemandaEntity;
import com.autoerp.model.servico.OrdemServicoEntity;
import com.autoerp.model.servico.PecaEntity;
import com.autoerp.model.servico.ServicoEntity;
import com.autoerp.model.servico.ServicoPrestadoEntity;
import com.mysql.jdbc.Field;

public class AppManager_OLD extends ApplicationManager {

	private Props props;

	@Override
	public void init(Context application) {

		this.props = getProps();

		// //////////////////////////////////////////
		// TURN ON/OFF DEBUG MODE
		// //////////////////////////////////////////
		setDebugMode(props.getBoolean("debug_mode"));

		// /////////////////////////////////////////////////
		// TURN ON/OFF APP MANAGER AUTO-REDEPLOY FEATURE
		// OBS: Requires http://www.javarebel.com to work
		// /////////////////////////////////////////////////
		setReloadable(props.getBoolean("auto_reload"));

		// ////////////////////////////////////////
		// FOR SENDING EMAIL
		// ////////////////////////////////////////
		if (!props.getBoolean("email.send_email")) {

			Email.setSendEmail(false);

		} else {

			Email.setDefaultHostName(props.getString("email.host"));

			Email.setDefaultSslConnection(props.getBoolean("email.ssl"));

			Email.setDefaultPort(props.getInt("email.port"));

			if (props.getBoolean("email.use_authentication")) {

				Email.setDefaultAuthentication(props.getString("email.user"),
						props.getString("email.pass"));
			}

			Email.setDefaultFrom(props.getString("email.from_email"),
					props.getString("email.from_name"));
		}
	}

	@Override
	public ConnectionHandler createConnectionHandler() {

		String driver = props.getString("jdbc.driver");
		String url = props.getString("jdbc.url");
		String user = props.getString("jdbc.user");
		String pass = props.getString("jdbc.pass");

		return new MySQLBoneCPConnectionHandler(driver, url, user, pass);
	}

	@Override
	public void setupDB() {
		initDatabaseIfNeeded();
	}

	@Override
	public void loadBeans() {
		/*
		 * bean(User.class, "Users") .pk("id", DBTypes.AUTOINCREMENT)
		 * .field("username", DBTypes.STRING) .field("password", DBTypes.STRING)
		 * .field("email", DBTypes.STRING) .field("languageId", "language_id",
		 * DBTypes.INTEGER) .field("groupId", "group_id", DBTypes.INTEGER);
		 */

		// Mapeando a tabela "tb_usuario" para o bean do modulo USUARIO
		bean(UsuarioEntity.class, "tb_usuario")

		.pk("id_usuario", DBTypes.AUTOINCREMENT)
				.field("de_usuario", DBTypes.STRING)
				.field("de_login", DBTypes.STRING)
				.field("de_senha", DBTypes.STRING)
				.field("id_grupo", DBTypes.INTEGER);

		// Mapeando a tabela "tb_uf" para o bean do modulo
		// ADMINISTRACAO/UfEntity
		UfEntity ufPxy = PropertiesProxy.create(UfEntity.class);

		bean(UfEntity.class, "tb_uf")

		.pk(ufPxy.getId_uf(), "id_uf", DBTypes.AUTOINCREMENT)
				.field(ufPxy.getSigla_uf(), "sigla_uf", DBTypes.STRING)
				.field(ufPxy.getDe_nome(), "de_nome", DBTypes.STRING);

		// Mapeando a tabela "tb_cidade" para o bean do modulo
		// ADMINISTRACAO/CidadeEntity
		CidadeEntity cidadePxy = PropertiesProxy.create(CidadeEntity.class);

		bean(CidadeEntity.class, "tb_cidade")
				.pk(cidadePxy.getId_cidade(), "id_cidade",
						DBTypes.AUTOINCREMENT)
				.field(cidadePxy.getUfEntity().getId_uf(), "id_uf_fk",
						DBTypes.INTEGER)
				.field(cidadePxy.getUfEntity().getSigla_uf(), "sigla_uf",
						DBTypes.STRING)
				.field(cidadePxy.getDe_cidade(), "de_cidade", DBTypes.STRING);

		// Mapeando a tabela "tb_cliente" para o bean do modulo CLIENTE
		ClienteEntity clientePxy = PropertiesProxy.create(ClienteEntity.class);

		bean(ClienteEntity.class, "tb_cliente")

				.pk(clientePxy.getId_cliente(), "id_cliente",
						DBTypes.AUTOINCREMENT)
				.field(clientePxy.getNu_rg(), "nu_rg", DBTypes.INTEGER)
				.field(clientePxy.getDe_orgao_expeditor(),
						"de_orgao_expeditor", DBTypes.STRING)
				.field(clientePxy.getNu_cpf(), "nu_cpf", DBTypes.STRING)
				.field(clientePxy.getDe_nome(), "de_nome", DBTypes.STRING)
				.field(clientePxy.getNu_tel_residencial(),
						"nu_tel_residencial", DBTypes.INTEGER)
				.field(clientePxy.getNu_tel_celular(), "nu_tel_celular",
						DBTypes.INTEGER)
				.field(clientePxy.getNu_tel_comercial(), "nu_tel_comercial",
						DBTypes.INTEGER)
				.field(clientePxy.getDe_endereco(), "de_endereco",
						DBTypes.STRING)
				.field(clientePxy.getCidade().getId_cidade(), "id_cidade_fk",
						DBTypes.INTEGER)
				.field(clientePxy.getDe_bairro(), "de_bairro", DBTypes.STRING)
				.field(clientePxy.getNu_cep(), "nu_cep", DBTypes.INTEGER)
				.field(clientePxy.getDe_email(), "de_email", DBTypes.STRING);

		// Mapeando a tabela "tb_carro" para o bean do modulo CARRO
		CarroEntity carroPxy = PropertiesProxy.create(CarroEntity.class);

		bean(CarroEntity.class, "tb_carro")

				.pk(carroPxy.getId_carro(), "id_carro", DBTypes.AUTOINCREMENT)
				.field(carroPxy.getCliente().getId_cliente(), "id_cliente_fk",
						DBTypes.INTEGER)
				.field(carroPxy.getDe_placa(), "de_placa", DBTypes.STRING)
				.field(carroPxy.getDe_modelo(), "de_modelo", DBTypes.STRING)
				.field(carroPxy.getDe_marca(), "de_marca", DBTypes.STRING)
				.field(carroPxy.getDe_cor(), "de_cor", DBTypes.STRING)
				.field(carroPxy.getDt_ano(), "dt_ano", DBTypes.STRING)
				.field(carroPxy.getNu_qtd_combustivel(), "nu_qtd_combustivel",
						DBTypes.INTEGER)
				.field(carroPxy.getDe_observacao(), "de_observacao",
						DBTypes.STRING);
		
		// Mapeando a tabela "tb_peca" para o bean do modulo SERVIÇO/PecaEntity
		PecaEntity pecaPxy = PropertiesProxy.create(PecaEntity.class);

		bean(PecaEntity.class, "tb_peca")
			.pk(pecaPxy.getId_peca(), "id_peca", DBTypes.AUTOINCREMENT)
			.field(pecaPxy.getDe_nome(), "de_nome", DBTypes.STRING)
			.field(pecaPxy.getNu_preco(),"nu_preco",DBTypes.FLOAT);
		
		// Mapeando a tabela "tb_demanda" para o bean do modulo SERVIÇO/DemandaEntity
		DemandaEntity demandaPxy = PropertiesProxy.create(DemandaEntity.class);
		
		bean(DemandaEntity.class,"tb_demanda")
			.pk(demandaPxy.getId_demanda(),"id_demanda",DBTypes.AUTOINCREMENT)
			.field(demandaPxy.getNu_preco(),"nu_preco",DBTypes.FLOAT)
			.field(demandaPxy.getNu_quat_pecas(),"nu_quat_pecas",DBTypes.INTEGER)
			.field(demandaPxy.getOrdemServico().getId_ordem_servico(),"id_ordem_servico_fk",DBTypes.INTEGER)
			.field(demandaPxy.getPeca().getId_peca(),"id_peca_fk",DBTypes.INTEGER);
		
		// Mapeando a tabela "tb_ordem_servico" para o bean do modulo SERVIÇO/OrdemServicoEntity
		OrdemServicoEntity ordemServicoPxy = PropertiesProxy.create(OrdemServicoEntity.class);
		
		bean(OrdemServicoEntity.class,"tb_ordem_servico")
		.pk(ordemServicoPxy.getId_ordem_servico(),"id_ordem_servico", DBTypes.AUTOINCREMENT)
		.field(ordemServicoPxy.getNu_km_entrada(),"nu_km_entrada", DBTypes.INTEGER)
		.field(ordemServicoPxy.getNu_km_saida(),"nu_km_saida", DBTypes.INTEGER)
		.field(ordemServicoPxy.getDt_entrada(),"dt_entrada",DBTypes.NOW_ON_BOTH_TIMESTAMP )
		.field(ordemServicoPxy.getDt_saida(),"dt_saida", DBTypes.NOW_ON_BOTH_TIMESTAMP )
		.field(ordemServicoPxy.getStatus(),"status", DBTypes.BYTE_ARRAY)
		.field(ordemServicoPxy.getNu_valor_total(),"nu_valor_total",DBTypes.FLOAT)
		.field(ordemServicoPxy.getCarro().getId_carro(),"id_carro_fk",DBTypes.INTEGER)
		.field(ordemServicoPxy.getFuncionario().getId_funcionario(),"id_funcionario_fk",DBTypes.INTEGER);
	
		
		// Mapeando a tabela "tb_servico" para o bean do modulo SERVIÇO/ServicoEntity
		ServicoEntity servicoPxy = PropertiesProxy.create(ServicoEntity.class);
		
		bean(ServicoEntity.class,"tb_servico")
		.pk(servicoPxy.getId_servico(),"id_servico", DBTypes.AUTOINCREMENT)
		.field(servicoPxy.getNu_preco(),"nu_preco",DBTypes.FLOAT)
		.field(servicoPxy.getDe_nome(), "nome_no", DBTypes.STRING)
		.field(servicoPxy.getDe_descricao(), "de_descricao", DBTypes.STRING);
		
		// Mapeando a tabela "tb_servico_prestado" para o bean do modulo SERVIÇO/ServicoPrestadoEntity
				ServicoPrestadoEntity  servicoPrestadoPxy = PropertiesProxy.create(ServicoPrestadoEntity.class);
				
				bean(ServicoPrestadoEntity.class,"tb_servico_prestado")
					.pk(servicoPrestadoPxy.getId_servico_prestado(),"id_servico_prestado",DBTypes.AUTOINCREMENT)
					.field(servicoPrestadoPxy.getNu_preco(),"nu_preco",DBTypes.FLOAT)
					.field(servicoPrestadoPxy.getOrdemServico().getId_ordem_servico(),"id_ordem_servico_fk",DBTypes.INTEGER)
					.field(servicoPrestadoPxy.getServico().getId_servico(),"id_servico_fk",DBTypes.INTEGER);
		
		
		
	}

	@Override
	public void loadLists() {
		// addLocalizedLists("groups", "languages");

		DBListData listaUf = new DBListData("listaUf", "id_uf", "de_nome",
				"tb_uf", "de_nome");
		addList(listaUf, getConnectionHandler());

	}

	@Override
	public void loadLocales() {
		// addLocale(Language.ENGLISH.getLocale());
		// addLocale(Language.PORTUGUESE.getLocale());

		// Adicionar o locale brasileiro
		addLocale(new Locale("pt", "BR"));
	}

	@Override
	public void loadFilters() {

		filter(new ExceptionFilter());
		on(EXCEPTION, fwd("/jsp/error.jsp"));

		filter(new MentaContainerFilter());

		filter(new AuthenticationFilter());
		on(LOGIN, redir("/jsp/login.jsp"));

		// filter(new ValidationFilter());

		filter(new TransactionFilter());
	}

	// Inversão de Controle
	@Override
	public void setupIoC() {

		ioc(BeanSession.class, props.getClass("mentabean.dialect"));

		// ioc(UserDAO.class, JdbcUserDAO.class);

		ioc(UsuarioDAO.class, UsuarioDAOJdbc.class);

		// ioc CIDADE
		ioc(CidadeDAO.class, CidadeDAOJdbc.class);

		ioc(UfDAO.class, UfDAOJdbc.class);

		// ioc CLIENTE
		ioc(ClienteDAO.class, ClienteDAOJdbc.class);

		// ioc CARRO
		ioc(CarroDAO.class, CarroDAOJdbc.class);
		
		// ioc ORDEM DE SERVICO
		ioc(OrdemServicoDAO.class, OrdemServicoDAOJdbc.class);
		
		// ioc PEÇA
		ioc(PecaDAO.class, PecaDAOJdbc.class);
		
		// ioc DEMANDA
		ioc(DemandaDAO.class,DemandaDAOJdbc.class);
		
		// ioc SERVICO
		ioc(ServicoDAO.class, ServicoDAOJdbc.class);
		
		// ioc SERVICO PRESTADO
		ioc(ServicoPrestadoDAO.class, ServicoPrestadoDAOJdbc.class);
		
	}

	@Override
	public void loadActions() {
		/*
		action("/User", UserAction.class, "add")
			.bypassAuthentication()
			.on(ERROR, fwd("/jsp/user/add.jsp"))
			.on(CREATED, redir("/jsp/index.jsp"));
		
		action("/User", UserAction.class, "edit")
			.comeBackAfterLogin()
			.authorize(Group.ADMIN, Group.MASTER)
			.filter(new BlacklistParamFilter("id")) // project against param injection
			.on(ERROR, fwd("/jsp/user/edit.jsp"))
			.on(SHOW, fwd("/jsp/user/edit.jsp"))
			.on(UPDATED, redir("/jsp/index.jsp"));
		
		action("/User", UserAction.class, "check")
			.bypassAuthentication()
			.all(ajax(new ResultRenderer())); // return text/plain with the result...
	
		
		
		action("/Logout", LogoutAction.class)
			.on(SUCCESS, redir("/jsp/login.jsp"));
			
			action("CidadeAction",CidadeAction.class, "getCidades")
        .on(SUCCESS, ajax(new JsonRenderer()));
			
			*/
		action("/Usuario", UsuarioAction.class, "adicionar")
		.bypassAuthentication()
		.on(CREATED,fwd("/jsp/usuario/editar.jsp"));
		
		//Registro da action LOGIN
		action("/Login", LoginAction.class)
		.bypassAuthentication()
		.on(ERROR, redir("/jsp/login.jsp"))
		.on(SUCCESS, redir("/jsp/index.jsp"));
		
		//Registro da action CIDADE		
		action("jsp/cliente/CidadeAction",CidadeAction.class,"getCidades")
		.bypassAuthentication()
		.on(SUCCESS, new AjaxConsequence(new JSONGenericRenderer()));
		
		//Registro da action CLIENTE
		action("/Cliente",ClienteAction.class,"adicionar")
		.bypassAuthentication()
		.on(CREATED,fwd("/jsp/carro/adicionar.jsp"));
		
		action("/Cliente",ClienteAction.class,"buscar")
		.bypassAuthentication()
		.on(SUCCESS,fwd("/jsp/cliente/listar.jsp"));
		
		action("/Cliente",ClienteAction.class,"editar")
		.bypassAuthentication()
		.filter(new BlacklistParamFilter("id")) // project against param injection
		.on(ERROR, fwd("/jsp/cliente/editar.jsp"))
		.on(SHOW, fwd("/jsp/cliente/editar.jsp"))
		.on(UPDATED, redir("/jsp/index.jsp"));
		
		action("/Cliente",ClienteAction.class,"listar")
		.bypassAuthentication()
		.on(SUCCESS,fwd("/jsp/cliente/listar.jsp"));
		
		
		//Registro da action CARRO
		action("/Carro",CarroAction.class,"adicionar")
		.bypassAuthentication()
		.on(CREATED,fwd("/jsp/index.jsp"));
		
		//Registro da action ORDEM DE SERVICO
		 action("/OrdemServico",OrdemServicoAction.class,"adicionar")
			.bypassAuthentication()
			.on(CREATED,fwd("/jsp/index.jsp"));
		 
		action("/OrdemServico",OrdemServicoAction.class,"listarClientes")
		.bypassAuthentication()
		.on(SUCCESS,fwd("/jsp/servico/buscarCliente.jsp"));
		
		action("/OrdemServico",OrdemServicoAction.class,"listarOS")
		.bypassAuthentication()
		.on(SUCCESS,fwd("/jsp/servico/listarOS.jsp"));
		
		action("/OrdemServico",OrdemServicoAction.class,"listarPecas")
		.bypassAuthentication()
		.on(SUCCESS,new AjaxConsequence(new JSONGenericRenderer()));
		
		action("/OrdemServico",OrdemServicoAction.class,"listarServicos")
		.bypassAuthentication()
		.on(SUCCESS,new AjaxConsequence(new JSONGenericRenderer()));
		
		action("/OrdemServico",OrdemServicoAction.class,"exibirPeca")
		.bypassAuthentication()
		.on(SUCCESS,new AjaxConsequence(new JSONGenericRenderer()));
		
		action("/OrdemServico",OrdemServicoAction.class,"exibirServico")
		.bypassAuthentication()
		.on(SUCCESS,new AjaxConsequence(new JSONGenericRenderer()));
		
		action("/OrdemServico",OrdemServicoAction.class,"addDemandaServico")
		.bypassAuthentication()
		.on(SUCCESS,new AjaxConsequence(new JSONGenericRenderer(1)));
		
		action("/OrdemServico",OrdemServicoAction.class,"addDemandaPeca")
		.bypassAuthentication()
		.on(SUCCESS,new AjaxConsequence(new JSONGenericRenderer(1)));
		
		action("/OrdemServico",OrdemServicoAction.class,"excluirItemDemandaPeca")
		.bypassAuthentication()
		.on(SUCCESS,new AjaxConsequence(new JSONGenericRenderer(1)));
		
		action("/OrdemServico",OrdemServicoAction.class,"excluirItemDemandaServico")
		.bypassAuthentication()
		.on(SUCCESS,new AjaxConsequence(new JSONGenericRenderer(1)));
				 				
		action("/OrdemServico",OrdemServicoAction.class,"buscarCliente")
		.bypassAuthentication()
		.on(SUCCESS,fwd("/jsp/servico/buscarCliente.jsp"));
		
		action("/OrdemServico",OrdemServicoAction.class,"novaOS")
		.bypassAuthentication()
		.on(SHOW,fwd("/jsp/servico/buscarCarro.jsp"))
		.on(SUCCESS, fwd("/jsp/servico/adicionarOS.jsp"));
						
		 
	}

	// //////////////////////////////////////////////////////////////////////////////
	// Database initialization so this app does not require any database setup
	//
	// NOTE: It is not necessary to do this if your database is already
	// initialized
	// //////////////////////////////////////////////////////////////////////////////

	private void initDatabaseIfNeeded() {

		final ConnectionHandler connHandler = getConnectionHandler();

		connHandler.exec(new ConnectionHandler.Exec() {

			@Override
			public void exec(Connection conn) {
				initDatabaseIfNeeded(conn);
			}
		});
	}

	protected void initDatabaseIfNeeded(Connection conn) {

		if (SQLUtils.checkIfTableExists(conn, "tb_usuario"))
			return;

		try {
			String file = props.getAbsolutePath("db.script");
			SQLUtils.executeScript(conn, file, "UTF-8");
		} catch (Exception e) {
			e.printStackTrace();
		}

		if (!SQLUtils.checkIfTableExists(conn, "tb_usuario"))
			throw new RuntimeException("Failed to initialize db!");
	}
}